import copy
import sys
import pickle
from enum import Enum

import pygame
from setting import *

import tkinter as tk
from tkinter.filedialog import askopenfilename, asksaveasfilename

import logging
logging.basicConfig(level = logging.INFO,format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
#生成日志句柄
# logger = logging.getLogger("wqbin")
logging.info("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")

sys.setrecursionlimit(15000)
print(sys.getrecursionlimit())

class MapType(Enum):
    BLANK = 0
    TREE = 1
    WALL = 2
    GIFT = 3

map_data = []
pen_type = MapType.BLANK

path = []


start_image = pygame.image.load("img/soldier.png")
start_image = pygame.transform.scale(start_image, (GRID_SIZE, GRID_SIZE))

target_image = pygame.image.load("img/star2.png")
target_image = pygame.transform.scale(target_image, (GRID_SIZE, GRID_SIZE))

def init_map_data():
    map_data.clear()
    row_num = SCREEN_HEIGHT // GRID_SIZE
    col_num = SCREEN_WIDTH // GRID_SIZE
    for r in range(row_num):
        line = []
        for c in range(col_num):
            line.append(MapType.BLANK.value)
        map_data.append(line)

def draw_grid():
    for row in range(1, SCREEN_HEIGHT // GRID_SIZE):
        pygame.draw.line(screen, "skyblue",
                         (0, row * GRID_SIZE), (SCREEN_WIDTH, row * GRID_SIZE))
    for col in range(1, SCREEN_WIDTH // GRID_SIZE):
        pygame.draw.line(screen, "skyblue",
                         (col * GRID_SIZE, 0), (col * GRID_SIZE, SCREEN_HEIGHT))


def draw_map():
    cell_color = "green"
    for row_index, row in enumerate(map_data):
        for col_index, cell in enumerate(row):
            if cell == MapType.TREE.value:
                cell_color = "green"
            if cell == MapType.WALL.value:
                cell_color = "orange"
            if cell == MapType.GIFT.value:
                cell_color = "red"
            if cell is not MapType.BLANK.value:
                pygame.draw.rect(screen, cell_color,
                                 (col_index * GRID_SIZE + 1, row_index * GRID_SIZE + 1, GRID_SIZE - 2, GRID_SIZE - 2))


def draw_icon():
    mx, my = pygame.mouse.get_pos()
    row = my // GRID_SIZE
    col = mx // GRID_SIZE

    pen_color = "darkgreen"

    pygame.draw.rect(screen, "yellow",
                     (col * GRID_SIZE, row * GRID_SIZE, GRID_SIZE, GRID_SIZE), 2)

    if pen_type is MapType.TREE:
        pen_color = "green"
    if pen_type is MapType.WALL:
        pen_color = "orange"
    if pen_type is MapType.GIFT:
        pen_color = "red"
    if pen_type is MapType.BLANK:
        pen_color = "darkgreen"

    pygame.draw.rect(screen, pen_color,
                     (col * GRID_SIZE + 2, row * GRID_SIZE + 2,
                      GRID_SIZE - 4, GRID_SIZE - 4))

def draw_start():
    screen.blit(start_image, (g_start_pos[1] * GRID_SIZE, g_start_pos[0] * GRID_SIZE))


def draw_target():
    screen.blit(target_image, (g_target_pos[1] * GRID_SIZE, g_target_pos[0] * GRID_SIZE))

def draw_path():
    for point in path:
        pygame.draw.circle(screen, "skyblue",
                           (point[1] * GRID_SIZE + GRID_SIZE // 2, point[0] * GRID_SIZE + GRID_SIZE // 2),
                           GRID_SIZE // 4)


# -------------    ---------------------

init_map_data()
map_data[2][5] = MapType.WALL.value
map_data[3][1] = MapType.TREE.value
map_data[4][ 4] = MapType.GIFT.value
print(map_data)

# -------------  FIND PATH  ---------------------
def is_right_blank(pos, map):
    logging.info("[->] check right.")
    if pos[1] >= SCREEN_WIDTH // GRID_SIZE - 1:
        return False
    cell = map[pos[0]][pos[1] + 1]
    if cell == 0:
        return True
    else:
        return False

def is_up_blank(pos, map):
    logging.info("[^] check up.")
    if pos[0] <= 0:
        return False
    cell = map[pos[0] - 1][pos[1]]
    if cell == 0:
        return True
    else:
        return False

def is_left_blank(pos, map):
    logging.info("[<-] check left.")
    if pos[1] <= 0:
        return False
    cell = map[pos[0]][pos[1] - 1]
    if cell == 0:
        return True
    else:
        return False

def is_down_blank(pos, map):
    logging.info("[v] check down.")
    if pos[0] >= SCREEN_HEIGHT // GRID_SIZE - 1:
        return False
    cell = map[pos[0] + 1][pos[1]]
    if cell == 0:
        return True
    else:
        return False



def find_path(start_pos, target_pos, exp_map, path, dir):
    logging.info(f"{start_pos} ...")

    find_num = 0

    updown = "up" if g_start_pos[0] >= g_target_pos[0] else "down"
    print(updown)

    # 如果 start_pos == target_pos ,返回
    if start_pos[0] == target_pos[0] and start_pos[1] == target_pos[1]:
        return True
    # 如果上下左右都是障碍，则将 start_pos 标成障碍
    #
    # 如果右边是空地，将该地加入路径， 向右找路，  将该地从路径删除
    if is_right_blank(start_pos, exp_map) and dir != "left":
        next_pos = (start_pos[0], start_pos[1]  + 1)
        path.append(next_pos)
        if find_path(next_pos, target_pos, exp_map, path, "right"):
            return True
        else:
            exp_map[next_pos[0]][next_pos[1]] = -1
            path.pop()
            find_num += 1
    else:
        find_num += 1

    # 如果上边是空地，将该地加入路径， 向右找路， 将该地从路径删除
    if updown == "up":
        if is_up_blank(start_pos, exp_map) and dir != "down":
            next_pos = (start_pos[0] - 1, start_pos[1])
            path.append(next_pos)
            if find_path(next_pos, target_pos, exp_map, path, "up"):
                return True
            else:
                path.pop()
                exp_map[next_pos[0]][next_pos[1]] = -1
                find_num += 1
        else:
            find_num += 1

    # 如果下边是空地，将该地加入路径， 向下找路， 将该地从路径删除
    if updown == "down":
        if is_down_blank(start_pos, exp_map) and dir != "up":
            next_pos = (start_pos[0] + 1, start_pos[1])
            path.append(next_pos)
            if find_path(next_pos, target_pos, exp_map, path, "down"):
                return True
            else:
                exp_map[next_pos[0]][next_pos[1]] = -1
                path.pop()
                find_num += 1
        else:
            find_num += 1

    # 如果左边是空地，将该地加入路径， 向左找路， 将该地从路径删除
    if is_left_blank(start_pos, exp_map) and dir != "right":
        next_pos = (start_pos[0], start_pos[1] - 1)
        path.append(next_pos)
        if find_path(next_pos, target_pos, exp_map, path, "left"):
            return True
        else:
            exp_map[next_pos[0]][next_pos[1]] = -1
            path.pop()
            find_num += 1
    else:
        find_num += 1

    # 如果上下左右都没路，将该地标成障碍
    logging.info(find_num)
    if find_num == 4:
        exp_map[start_pos[0]][start_pos[1]] = -1
        print(f"{start_pos} set to -1")
        return False

# -------------  START  ---------------------

pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
clock = pygame.time.Clock()
pygame.display.set_caption("地图编辑器")
# pygame.mouse.set_visible(False)

running = True

while running:
    # event
    event_list = pygame.event.get()
    for e in event_list:
        if e.type == pygame.QUIT:
            running = False
        if e.type == pygame.KEYDOWN:
            if e.key == pygame.K_0 or e.key == pygame.K_KP0:
                pen_type = MapType.BLANK
            if e.key == pygame.K_1 or e.key == pygame.K_KP1:
                pen_type = MapType.TREE
            if e.key == pygame.K_2 or e.key == pygame.K_KP2:
                pen_type = MapType.WALL
            if e.key == pygame.K_3 or e.key == pygame.K_KP3:
                pen_type = MapType.GIFT
            if e.key == pygame.K_s:
                print("save map")
                root = tk.Tk()
                root.overrideredirect(True)
                root.attributes("-alpha", 0)
                file_name = asksaveasfilename(
                    defaultextension="*.dat",
                    filetypes=[("Map file", "*.dat")])
                root.destroy()
                with open(file_name, "wb") as f:
                    pickle.dump(map_data, f)
            if e.key == pygame.K_l:
                print("load map")
                # with open("map.dat", "rb") as f:
                #     map_data = pickle.load(f)
                root = tk.Tk()
                root.overrideredirect(True)
                root.attributes("-alpha", 0)
                file_name = askopenfilename(filetypes=[("Map file", "*.dat")])
                root.destroy()
                if file_name:
                    with open(file_name, "rb") as f:
                        map_data = pickle.load(f)
            if e.key == pygame.K_c:
                init_map_data()
            if e.key == pygame.K_g:
                print("go go go ~~")
                path.clear()
                print(path)

                exp_map = copy.deepcopy(map_data)
                exp_map[g_start_pos[0]][g_start_pos[1]] = -1
                find_path(g_start_pos, g_target_pos, exp_map, path, "begin" )

                print("After gone:")
                print(path)

    # update
    if(pygame.mouse.get_pressed(3)[0] == 1):
        mx, my = pygame.mouse.get_pos()
        row = my // GRID_SIZE
        col = mx // GRID_SIZE
        map_data[row][col] = pen_type.value

    # draw
    screen.fill("darkgreen")
    draw_grid()
    draw_map()
    draw_icon()
    draw_start()
    draw_target()
    draw_path()
    pygame.display.flip()

    # fps
    clock.tick(FPS)

pygame.quit()
sys.exit()